﻿#include "util/fne.h"


namespace fne
{
	static PFN_NOTIFY_SYS s_pfn_notify_sys = nullptr;
	static PFN_NOTIFY_SYS s_pfnuser_notify_sys = nullptr;


	INT WINAPI NotifySys(INT nMsg, DWORD dwParam1, DWORD dwParam2)
	{
		if (s_pfn_notify_sys != nullptr)
			return s_pfn_notify_sys(nMsg, dwParam1, dwParam2);
		return 0;
	}

	INT WINAPI ProcessNotifyLib(INT nMsg, DWORD dwParam1, DWORD dwParam2)
	{
		INT nRet = NR_OK;
		switch (nMsg)
		{
		case NL_SYS_NOTIFY_FUNCTION:
			{
				s_pfn_notify_sys = reinterpret_cast<PFN_NOTIFY_SYS>(dwParam1);
				break;
			}
		case NL_FREE_LIB_DATA:

			return NR_OK;
		case NL_GET_CMD_FUNC_NAMES:
			//应返回所有命令和方法实现函数的函数名称数组, 
			//此数组必须与命令和方法定义数组一一对应, 
			//数组各成员均为对应函数的函数名称文本指针(char*)；

			break;
		case NL_GET_NOTIFY_LIB_FUNC_NAME:
			//应返回“处理系统通知的函数”(即自身函数)的函数名称(char*)；

			break;
		case NL_GET_DEPENDENT_LIBS:
			//应返回“依赖的第三方静态库文件列表”, 格式为\0分隔的文本, 结尾两个\0。

			break;
		default:
			nRet = NR_ERR;
			break;
		}

		//调用用户代码
		if (s_pfnuser_notify_sys)
			nRet = s_pfnuser_notify_sys(nMsg, dwParam1, dwParam2);

		return nRet;
	}

	void append_to_binary(PMDATA_INF pArgInf, CBString& out)
	{
		if (!pArgInf->sys_type())
			return;
		if (pArgInf->is_array())
		{
			const auto ary_data = pArgInf->m_pAryData;
			switch (pArgInf->array_type())
			{
			case SDT_TEXT:
				for (int i = 0; i < array_size(ary_data); ++i)
				{
					const auto str = array_at<char*>(ary_data, i);
					out += CBStringView{str, static_cast<int>(strlen(str)) + 1};
				}
				break;
			case SDT_BIN:
				for (int i = 0; i < array_size(ary_data); ++i)
				{
					const auto& bin_data = array_at<char*>(ary_data, i);
					out += CBStringView{bin_data + 8, *reinterpret_cast<INT*>(bin_data + 4)};
				}
				break;
			default:
				const auto size = array_size(pArgInf->m_pAryData);
				out += CBStringView{
					static_cast<char*>(pArgInf->m_pAryData) + 8, static_cast<int>(size * pArgInf->size())
				};
			}
			return;
		}
		switch (pArgInf->m_dtDataType)
		{
		case SDT_TEXT:
			out += CBStringView{pArgInf->m_pText, static_cast<int>(strlen(pArgInf->m_pText)) + 1 };
			return;
		case SDT_BIN:
			out += CBStringView{pArgInf->m_pText + 8, *reinterpret_cast<int*>(pArgInf->m_pText + 4)};
			return;
		default:
			out += CBStringView{pArgInf, static_cast<int>(pArgInf->size())};
		}
	}

	void append_to_string(PMDATA_INF pArgInf, CBString& out)
	{
		char buf[64];
		if (pArgInf->is_array())
		{
			const auto ary_data = pArgInf->m_pAryData;
			switch (pArgInf->array_type())
			{
			case SDT_BOOL:
				for (size_t i = 0; i < array_size(ary_data); ++i)
				{
					out += array_at<BOOL>(ary_data, i) ? "真" : "假";
				}
				break;
			case SDT_BYTE:
				for (size_t i = 0; i < array_size(ary_data); ++i)
				{
					_itoa(array_at<BYTE>(ary_data, i), buf, 10);
					out += buf;
				}
				break;
			case SDT_SHORT:
				for (size_t i = 0; i < array_size(ary_data); ++i)
				{
					_itoa(array_at<SHORT>(ary_data, i), buf, 10);
					out += buf;
				}
				break;
			case SDT_INT:
			case SDT_SUB_PTR:
				for (size_t i = 0; i < array_size(ary_data); ++i)
				{
					_itoa(array_at<INT>(ary_data, i), buf, 10);
					out += buf;
				}
				break;
			case SDT_DATE_TIME:
				for (size_t i = 0; i < array_size(ary_data); ++i)
				{
					DateTimeFormat(buf, sizeof buf, array_at<DATE>(ary_data, i), FALSE);
					out += buf;
				}
				break;
			case SDT_FLOAT:
				for (size_t i = 0; i < array_size(ary_data); ++i)
				{
					_gcvt(array_at<FLOAT>(ary_data, i), 7, buf);
					out += buf;
				}
				break;
			case SDT_DOUBLE:
				for (size_t i = 0; i < array_size(ary_data); ++i)
				{
					_gcvt(array_at<DOUBLE>(ary_data, i), 7, buf);
					out += buf;
				}
				break;
			case SDT_INT64:
				for (size_t i = 0; i < array_size(ary_data); ++i)
				{
					_i64toa(array_at<INT64>(ary_data, i), buf, 10);
					out += buf;
				}
				break;
			case SDT_TEXT:
				for (size_t i = 0; i < array_size(ary_data); ++i)
				{
					out += array_at<char*>(ary_data, i);
				}
				break;
			case SDT_BIN:
				for (size_t i = 0; i < array_size(ary_data); ++i)
				{
					const auto bin_data = array_at<char*>(ary_data, i);
					out += CBStringView{bin_data + 8, *reinterpret_cast<INT*>(bin_data + 4)};
				}
				break;
			default:
				break;
			}
			return;
		}
		switch (pArgInf->m_dtDataType)
		{
		case SDT_BOOL:
			if (pArgInf->m_bool)
				strcpy(buf, "真");
			else
				strcpy(buf, "假");
			break;
		case SDT_BYTE:
		case SDT_SHORT:
		case SDT_INT:
		case SDT_SUB_PTR:
			_itoa(pArgInf->m_int, buf, 10);
			break;
		case SDT_DATE_TIME:
			DateTimeFormat(buf, sizeof buf, pArgInf->m_date, FALSE);
			break;
		case SDT_FLOAT:
			_gcvt(pArgInf->m_float, 7, buf);
			break;
		case SDT_DOUBLE:
			_gcvt(pArgInf->m_double, 7, buf);
			break;
		case SDT_INT64:
			_i64toa(pArgInf->m_int64, buf, 10);
			break;
		case SDT_TEXT:
			out += pArgInf->m_pText;
			return;
		case SDT_BIN:
			out += CBStringView{pArgInf->m_pText + 8, *reinterpret_cast<int*>(pArgInf->m_pText + 4)};
			return;
		default:
			buf[0] = '\0';
			break;
		}
		out += buf;
	}

	CBString to_binary(PMDATA_INF pArgInf)
	{
		if (!pArgInf->sys_type())
			return {};
		if (pArgInf->is_array())
		{
			CBString ret{};
			const auto ary_data = pArgInf->m_pAryData;
			switch (pArgInf->array_type())
			{
			case SDT_TEXT:
				for (size_t i = 0; i < array_size(ary_data); ++i)
				{
					const auto str = array_at<char*>(ary_data, i);
					ret += CBStringView{str, static_cast<int>(strlen(str)) + 1};
				}
				break;
			case SDT_BIN:
				for (size_t i = 0; i < array_size(ary_data); ++i)
				{
					auto bin_data = array_at<char*>(ary_data, i);
					ret += {bin_data + 8, *reinterpret_cast<INT*>(bin_data + 4)};
				}
				break;
			default:
				const auto size = array_size(pArgInf->m_pAryData);
				return {static_cast<char*>(pArgInf->m_pAryData) + 8, static_cast<int>(size * pArgInf->size())};
			}
			return ret;
		}
		switch (pArgInf->m_dtDataType)
		{
		case SDT_TEXT:
			return {pArgInf->m_pText, static_cast<int>(strlen(pArgInf->m_pText)) + 1};
		case SDT_BIN:
			return {pArgInf->m_pText + 8, *reinterpret_cast<int*>(pArgInf->m_pText + 4)};
		default:
			return {pArgInf, static_cast<int>(pArgInf->size())};
		}
	}

	CBString to_string(PMDATA_INF pArgInf)
	{
		char buf[64];
		if (pArgInf->is_array())
		{
			CBString ret{};
			const auto ary_data = pArgInf->m_pAryData;
			switch (pArgInf->array_type())
			{
			case SDT_BOOL:
				for (size_t i = 0; i < array_size(ary_data); ++i)
				{
					ret += array_at<BOOL>(ary_data, i) ? "真" : "假";
				}
				break;
			case SDT_BYTE:
				for (size_t i = 0; i < array_size(ary_data); ++i)
				{
					_itoa(array_at<BYTE>(ary_data, i), buf, 10);
					ret += buf;
				}
				break;
			case SDT_SHORT:
				for (size_t i = 0; i < array_size(ary_data); ++i)
				{
					_itoa(array_at<SHORT>(ary_data, i), buf, 10);
					ret += buf;
				}
				break;
			case SDT_INT:
			case SDT_SUB_PTR:
				for (size_t i = 0; i < array_size(ary_data); ++i)
				{
					_itoa(array_at<INT>(ary_data, i), buf, 10);
					ret += buf;
				}
				break;
			case SDT_DATE_TIME:
				for (size_t i = 0; i < array_size(ary_data); ++i)
				{
					DateTimeFormat(buf, sizeof buf, array_at<DATE>(ary_data, i), FALSE);
					ret += buf;
				}
				break;
			case SDT_FLOAT:
				for (size_t i = 0; i < array_size(ary_data); ++i)
				{
					_gcvt(array_at<FLOAT>(ary_data, i), 7, buf);
					ret += buf;
				}
				break;
			case SDT_DOUBLE:
				for (size_t i = 0; i < array_size(ary_data); ++i)
				{
					_gcvt(array_at<DOUBLE>(ary_data, i), 7, buf);
					ret += buf;
				}
				break;
			case SDT_INT64:
				for (size_t i = 0; i < array_size(ary_data); ++i)
				{
					_i64toa(array_at<INT64>(ary_data, i), buf, 10);
					ret += buf;
				}
				break;
			case SDT_TEXT:
				for (size_t i = 0; i < array_size(ary_data); ++i)
				{
					ret += array_at<char*>(ary_data, i);
				}
				break;
			case SDT_BIN:
				for (size_t i = 0; i < array_size(ary_data); ++i)
				{
					auto bin_data = array_at<char*>(ary_data, i);
					ret += {bin_data + 8, *reinterpret_cast<INT*>(bin_data + 4)};
				}
				break;
			default:
				break;
			}
			return ret;
		}
		switch (pArgInf->m_dtDataType)
		{
		case SDT_BOOL:
			if (pArgInf->m_bool)
				strcpy(buf, "真");
			else
				strcpy(buf, "假");
			break;
		case SDT_BYTE:
		case SDT_SHORT:
		case SDT_INT:
		case SDT_SUB_PTR:
			_itoa(pArgInf->m_int, buf, 10);
			break;
		case SDT_DATE_TIME:
			DateTimeFormat(buf, sizeof buf, pArgInf->m_date, FALSE);
			break;
		case SDT_FLOAT:
			_gcvt(pArgInf->m_float, 7, buf);
			break;
		case SDT_DOUBLE:
			_gcvt(pArgInf->m_double, 7, buf);
			break;
		case SDT_INT64:
			_i64toa(pArgInf->m_int64, buf, 10);
			break;
		case SDT_TEXT:
			return pArgInf->m_pText;
		case SDT_BIN:
			return {pArgInf->m_pText + 8, *reinterpret_cast<int*>(pArgInf->m_pText + 4)};
		default:
			buf[0] = '\0';
			break;
		}
		return buf;
	}

	CBString to_string(int val)
	{
		char buf[64];
		_itoa(val, buf, 10);
		return buf;
	}

	CBString to_string(float val)
	{
		char buf[64];
		_gcvt(val, 10, buf);
		return buf;
	}

	CBString to_string(double val)
	{
		char buf[64];
		_gcvt(val, 10, buf);
		return buf;
	}

	CBString to_string(long long val)
	{
		char buf[64];
		_i64toa(val, buf, 10);
		return buf;
	}
}
